/*
 * Copyright (c) 2024 iSoftStone Education Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

#include "ohos_init.h"
#include "los_task.h"
#include "iot_errno.h"
#include "config_network.h"

#include <sys/time.h>
#include <time.h>
#include <math.h>

#include "ntp.h"

#include <stdint.h>
#include <stdbool.h>
#include <stdio.h>
#include <complex.h>

#define ROUTE_SSID                 "harmony-iot"
#define ROUTE_PASSWORD             "123456789"

#define LOG_SC_TAG                 "sc"
#define LOG_SC_TAG_INFO            "["LOG_SC_TAG"           %4d] "
#define LOG_SC_TAG_IOT             "["LOG_SC_TAG" iot       %4d] "
#define LOG_SC_TAG_NTP             "["LOG_SC_TAG" ntp       %4d] "
#define LOG_SC_TAG_KEY             "["LOG_SC_TAG" key       %4d] "
#define LOG_SC_TAG_ALARM           "["LOG_SC_TAG" alarm     %4d] "
#define LOG_SC_TAG_DISPLAY         "["LOG_SC_TAG" display   %4d] "


/***************************************************************
* 名   称: sc_ntp_time_t
* 说    明: 时间结构体
***************************************************************/
typedef struct
{
    int                        sync_status;        // ntp同步状态，0为未同步，1为同步
    int                        year;               // 年
    int                        month;              // 月
    int                        day;                // 日
    int                        hour;               // 时
    int                        min;                // 分
    int                        sec;                // 秒
} sc_ntp_time_t;

#define THREAD_START_INFO                                      \
{                                                              \
    int len = strlen(__FUNCTION__);                            \
    int count = (44 - len)/2;                                  \
    char temp[51] = {0};                                       \
    memset(temp, '=', count);                                  \
    memcpy(&temp[count], __FUNCTION__, len);                   \
    temp[strlen(temp)] = ' ';                                  \
    memcpy(&temp[strlen(temp)], "start", 5);                   \
    if(len%2)temp[strlen(temp)] = ' ';                         \
    memset(&temp[strlen(temp)], '=', count);                   \
    printf(LOG_SC_TAG_INFO"%s\r\n", __LINE__, temp);           \
}



WifiLinkedInfo wifiinfo;
/***************************************************************
* 函数名称: get_sta_link
* 说    明: 获取wifi连接信息
* 参    数: 
* 返 回 值: int 0连接，-1未连接
***************************************************************/
static int get_sta_link()
{
    
    WifiLinkedInfo *info = &wifiinfo;
    
    memset(info, 0, sizeof(WifiLinkedInfo));
    if (GetLinkedInfo(info) == WIFI_SUCCESS && info->connState == WIFI_CONNECTED && info->ipAddress != 0)
    {
        return 0;
    }
    
    return -1;
}



/***************************************************************
* 函数名称: sc_iot_thread
* 说    明: iot线程
* 参    数: void *args
* 返 回 值: 无
***************************************************************/
static void *sc_iot_thread(uint32_t args)
{

    uint8_t       buf[6]     = {0};
    uint8_t       hwaddr[6]  = {0x10, 0xdc, 0xb6, 0x92, 0x00, 0x00};
    
    THREAD_START_INFO
    int r = LzEfuseRead(21, 5, buf);
    if (r == 5)
    {
        memcpy(&hwaddr[1], buf, 5);                               // 以芯片唯一ID重新设置MAC地址
    }
    
    set_wifi_config_mode(NULL, (uint8_t *)"STA");                 // 配置为Wifi STA模式
    set_wifi_config_mac(NULL, hwaddr);
    set_wifi_config_route_ssid(NULL, (uint8_t *)ROUTE_SSID);
    set_wifi_config_route_passwd(NULL, (uint8_t *)ROUTE_PASSWORD);
    printf(LOG_SC_TAG_IOT"%smac:%02x:%02x:%02x:%02x:%02x:%02x\r\n",
           __LINE__, r == 5 ? "" : "注意使用默认mac,可能存在冲突 ",
           hwaddr[0], hwaddr[1], hwaddr[2], hwaddr[3], hwaddr[4], hwaddr[5]);
           
reconnect:
    SetWifiModeOff();
    SetWifiModeOn();
    
    while (1)
    {
        if (get_sta_link() != 0)
        {
            printf(LOG_SC_TAG_IOT"reconnect*********************\n", __LINE__);
            LOS_Msleep(1000);
            goto reconnect;
        }
        LOS_Msleep(30000);
    }
    return NULL;
}

/***************************************************************
* 函数名称: sc_ntp_thread
* 说    明: ntp同步时间，用于与NTP服务器进行时间同步
* 参    数:
*       @*args          智慧时钟设备的结构体指针
* 返 回 值: 无
***************************************************************/
static void *sc_ntp_thread(uint32_t args)
{
    
    uint32_t now_time   = 0;
    uint32_t ntp_time   = 0;
    time_t   now_time_t = 0;
    sc_ntp_time_t ntp_time_data;
    sc_ntp_time_t *ntp  = &ntp_time_data;
    int            time = 0;
    uint8_t  network_connect_last_status = 0;            // 网络最近连通状态标志，0为上一次为关闭，1为上一次为连通
    
    // ntp初始化
    THREAD_START_INFO
    if (get_sta_link() == 0)
    {
        ntp_init();
    }
    
    printf(LOG_SC_TAG_NTP"init finish\r\n", __LINE__);
    
    while (1)
    {
        // 如果网络已连通，则进行ntp同步
        if (get_sta_link() == 0)
        {
            if (network_connect_last_status == 0)
            {
                // 如果上一次网络未连通，则进行ntp重初始化
                network_connect_last_status = 1;
                ntp_reinit();
                LOS_Msleep(2000);
            }
            
            // 每隔60秒，进行ntp同步
            if ((++time) % 300 == 0 || ntp->sync_status == 0 || ntp->year > 2030)
            {
                printf(LOG_SC_TAG_NTP"ntp_time: %10lu start======\n", __LINE__, ntp_time);
                ntp_time = ntp_get_time(NULL);
                printf(LOG_SC_TAG_NTP"ntp_time: %10lu end  ======\n", __LINE__, ntp_time);
                if (ntp_time == 0)
                {
                    ntp->sync_status = 0;
                    now_time++;
                }
                else
                {
                    ntp->sync_status = 1;
                    now_time = ntp_time;
                }
            }
            else
            {
                now_time++;
            }
        }
        else
        {
            // 如果网络未连通，则不进行ntp同步，且ntp同步状态置为0
            ntp->sync_status = 0;
            network_connect_last_status = 0;
            // 如果未连通，则时间加1（即该任务是每隔1秒执行一次）
            now_time++;
        }
        
        // 获取本地时间
        now_time_t = (time_t)now_time;
        struct tm *now_tm = localtime(&now_time_t);
        // 赋值给公共结构体
        ntp->year  = now_tm->tm_year + 1900;
        ntp->month = now_tm->tm_mon + 1;
        ntp->day   = now_tm->tm_mday;
        ntp->hour  = now_tm->tm_hour;
        ntp->min   = now_tm->tm_min;
        ntp->sec   = now_tm->tm_sec;
        // 打印信息
        if (now_tm->tm_sec % 30 == 0)
        {
            printf(LOG_SC_TAG_NTP"sync_status: %s now_tm: %04d-%02d-%02d %02d:%02d:%02d\n",
                   __LINE__, (ntp->sync_status == 0) ? ("nosync") : ("sync"),
                   now_tm->tm_year + 1900,
                   now_tm->tm_mon + 1,
                   now_tm->tm_mday,
                   now_tm->tm_hour,
                   now_tm->tm_min,
                   now_tm->tm_sec);
        }
        // 等待950ms，上述任务需要消耗一定时间，预计为50msec
        LOS_Msleep(950);
    }
    return NULL;
}



/***************************************************************
 * 函数名称: create_task
 * 说    明: 创建任务
 * 参    数: unsigned int *threadID,  uint32_t size, uint8_t prio,
 *           TSK_ENTRY_FUNC func, void *args, const char *owner
 * 返 回 值: int
 ***************************************************************/
int create_task(unsigned int *threadID, uint32_t size, uint8_t prio, TSK_ENTRY_FUNC func, void *args, const char *owner)
{
    int ret = 0;
    TSK_INIT_PARAM_S task = {0};
    
    task.pfnTaskEntry = (TSK_ENTRY_FUNC)func;
    task.uwStackSize  = size;
    task.pcName       = (char *)owner;
    task.uwArg        = (uint32_t)args;
    task.usTaskPrio   = prio > 30 ? 30 : prio;
    ret = LOS_TaskCreate(threadID, &task);
    if (ret != LOS_OK)
    {
        printf("create_task", "%s ret = 0x%x\n", ret == LOS_OK ? "OK" : "FAILURE", ret);
    }
    
    return (ret == LOS_OK) ? IOT_SUCCESS : IOT_FAILURE;
}

/***************************************************************
* 函数名称: smart_clock_example
* 说    明: 智能时钟例程
* 参    数: 无
* 返 回 值: 无
***************************************************************/
void smart_clock_example(void)
{

    unsigned int thread_id1,thread_id2;

    LOS_Msleep(1000);
    printf(LOG_SC_TAG_INFO"欢迎使用 智能时钟\r\n", __LINE__);
    
    create_task(&thread_id1,1024 * 4,  20, sc_iot_thread, NULL , "sc iot");
    create_task(&thread_id2,1024 * 4,  20, sc_ntp_thread, NULL , "sc ntp");

}

APP_FEATURE_INIT(smart_clock_example);
